#pragma once 
#include<vector>
#include<queue>
#include"Lock.hpp"
#include"cond.hpp"
#include"Thread.hpp"



#define defaultnum 5
template<class T>
class ThreadPool
{
   
    ThreadPool(int num=defaultnum)
    :_threadsnum(num)
    {
        for(int i=0;i<_threadsnum;i++)
        {
             _Threads.emplace_back(
                [this](){
                    HandleRun();
            });
            std::cout<<"创建了一个线程 :"<<_Threads[i].Getname()<<std::endl;
        }
    }
    ~ThreadPool()
    {}
    ThreadPool<T> operator=(ThreadPool<T>)=delete;
    ThreadPool(const ThreadPool<T>&)=delete;
    //每个线程的回调函数：在任务队列中获取一个任务并执行
    void HandleRun()
    {
        while(1)
        {
            LockGuard lock(_mutex);
            while(_tasks.empty()&&_isrunning)
            {
                sleepnum++;
                _cond.Wait(_mutex);
                sleepnum--;
            }
            if(_tasks.empty()&&!_isrunning)
            {
                //线程中任务都执行完了，且线程池被设置要停止：
                break;
            }
            //到这里有两种情况：
            //1.线程池运行状态，任务队列有任务 2.线程池停止状态，任务队列有任务
            //第二种情况下要将任务执行完才能停止线程池
            T a=_tasks.front();
            _tasks.pop();
            a();
            std::cout<<"拿到了一个任务"<<std::endl;
        }
    }
    
    void Wake_One()
    {
        if(_isrunning)
        {
            _cond.Notify();
        }
    }
    void Wake_All()
    {
         if(_isrunning)
        {
            _cond.Notifyall();
        }
    }
public:
    //在任务队列中添加任务：
    void Equeue(T task)
    {
        LockGuard lock(_mutex);
        if(_isrunning)
        {
            _tasks.push(task);
            if(sleepnum==_Threads.size())
            {
                //如果都在休眠就唤醒一个线程
                Wake_One();
            }
        }
    }
    
    //启动线程池，线程池中的各个线程开始执行回调函数
    void Start()
    {
        if(!_isrunning)
        {
            _isrunning=true;
            for(auto th:_Threads)
            {
                th.Start();
            }
        }
    }
    //停止线程池
    void Stop()
    {
        if(!_isrunning)
        {
            return;
        }
        _isrunning=false;
        //唤醒所有线程：任务队列中有任务就执行，没任务就退出
        Wake_All();
    }
    //回收线程池中的线程
    void Join()
    {
        if(_isrunning)
        {
            return;
        }
        for(auto th:_Threads)
        {
            std::cout<<"回收了一个线程"<<th.Getname()<<std::endl;
            th.join();
        }
    }
    static ThreadPool<T>* GetInstance()
    {
        LockGuard lock(_Mutex);
        if(_ptr==nullptr)
        {
            _ptr=new ThreadPool<T>();
        }
        return _ptr;
    }
    private:
    std::vector<Thread> _Threads;
    std::queue<T> _tasks;
    int _threadsnum;
    int sleepnum;
    bool _isrunning=false;
    Cond _cond;
    Mutex _mutex;

    static ThreadPool<T>* _ptr;
    static Mutex _Mutex; 
};

template<class T>
ThreadPool<T>* ThreadPool<T>::_ptr=nullptr;
template<class T>
Mutex ThreadPool<T>::_Mutex;
